package admin

import (
	"ecms/models"
	"ecms/utils/reflects"
	"ecms/utils/repository"
	"ecms/utils/response"
	"ecms/utils/validator"
	"github.com/gin-gonic/gin"
	"time"
)

type RoleController struct {
}

// Index 角色列表
func (c *RoleController) Index(ctx *gin.Context) {
	type req struct {
		Page     int    `json:"page"`
		PageSize int    `json:"page_size"`
		Keyword  string `json:"keyword"`
		Status   int    `json:"status"`
	}
	reqData := &req{}
	rules := validator.NewRules(
		validator.NewRule("page", "分页页码", true, validator.TypeNumberNoneZero),
		validator.NewRule("page_size", "分页大小", true, validator.TypeNumberNoneZero),
		validator.NewRule("keyword", "搜索词", false, validator.TypeNoEmpty),
		validator.NewRule("status", "角色状态", true, validator.TypeStatus),
	)
	if !validator.ShouldBindFromPostForm(ctx, reqData, rules...) {
		return
	}

	lists := make([]models.AdminRole, 0)
	var total int64 = 0

	repo := repository.New(&models.AdminRole{})

	query := "status = ? AND is_deleted = 0"
	args := []interface{}{reqData.Status}
	if reqData.Keyword != "" {
		repo.BuildSearchQuery(&query, []string{"name", "description"}, reqData.Keyword, &args)
	}

	if !repo.Pagination(&repository.PaginationQuery{
		Out:      &lists,
		Page:     reqData.Page,
		PageSize: reqData.PageSize,
		Query:    query,
		Count:    &total,
		Args:     args,
		Order:    "sort ASC, updated_at DESC",
	}) {
		response.FailJson(ctx, "查询失败, 请稍后再试", nil)
		return
	}

	response.SuccessJson(ctx, "查询成功", struct {
		Lists []models.AdminRole `json:"lists"`
		Total int64              `json:"total"`
	}{
		Lists: lists,
		Total: total,
	})
}

// Create 角色创建
func (c *RoleController) Create(ctx *gin.Context) {
	reqData := &models.AdminRole{
		Status:    1,
		IsDeleted: 0,
		CreatedAt: response.Time(time.Now().Local()),
		UpdatedAt: response.Time(time.Now().Local()),
	}
	rules := validator.NewRules(
		validator.NewRule("name", "角色名称", true, validator.TypeNoEmpty),
		validator.NewRule("icon", "角色图标", false, validator.TypeNoEmpty),
		validator.NewRule("description", "角色简介", false, validator.TypeNoEmpty),
		validator.NewRule("sort", "排序", true, validator.TypeNumber),
	)
	if !validator.ShouldBindFromPostForm(ctx, reqData, rules...) {
		return
	}

	// 检查同名角色
	hasSame := &models.AdminRole{}
	repo := repository.New(&models.AdminRole{})
	if repo.Find(hasSame, "is_deleted = 0 AND name = ?", reqData.Name) && hasSame.Id != 0 {
		response.FailJson(ctx, "已存在同名角色", nil)
		return
	}

	// 创建
	if !repo.Create(reqData) {
		response.FailJson(ctx, "添加失败, 请稍后再试", nil)
		return
	}

	response.SuccessJson(ctx, "添加成功", nil)
}

// Update 角色编辑
func (c *RoleController) Update(ctx *gin.Context) {
	reqData := &models.AdminRole{}
	rules := validator.NewRules(
		validator.NewRule("id", "角色ID", true, validator.TypeNumberNoneZero),
		validator.NewRule("name", "角色名称", true, validator.TypeNoEmpty),
		validator.NewRule("icon", "角色图标", false, validator.TypeNoEmpty),
		validator.NewRule("description", "角色简介", false, validator.TypeNoEmpty),
		validator.NewRule("sort", "排序", true, validator.TypeNumber),
	)
	if !validator.ShouldBindFromPostForm(ctx, reqData, rules...) {
		return
	}

	// 检查同名角色
	hasSame := &models.AdminRole{}
	repo := repository.New(&models.AdminRole{})
	if repo.Find(hasSame, "is_deleted = 0 AND name = ? AND id <> ?", reqData.Name, reqData.Id) && hasSame.Id != 0 {
		response.FailJson(ctx, "已存在同名角色", nil)
		return
	}

	// 角色是否存在
	hasRole := &models.AdminRole{}
	if !repo.FindById(reqData.Id, hasRole) || hasRole.Id == 0 {
		response.FailJson(ctx, "角色信息已失效", nil)
		return
	}

	// 更新字段
	refObj, err := reflects.NewObject(hasRole)
	if err != nil {
		response.FailJson(ctx, "编辑失败, 请稍后再试", nil)
		return
	}
	fields := []string{"name", "icon", "description", "sort"}
	refObj.BatchSetValueFromFields(fields, reqData)
	hasRole.UpdatedAt = response.Time(time.Now().Local())

	if !repo.UpdateById(hasRole.Id, hasRole) {
		response.FailJson(ctx, "编辑失败, 请稍后再试", nil)
		return
	}

	response.SuccessJson(ctx, "编辑成功", nil)
}

// Delete 角色删除
func (c *RoleController) Delete(ctx *gin.Context) {
	reqData := &models.AdminRole{}
	rules := validator.NewRules(
		validator.NewRule("id", "角色ID", true, validator.TypeNumberNoneZero),
	)
	if !validator.ShouldBindFromPostForm(ctx, reqData, rules...) {
		return
	}

	hasRole := &models.AdminRole{}
	repo := repository.New(&models.AdminRole{})
	if !repo.Find(hasRole, "is_deleted = 0 AND id = ?", reqData.Id) || hasRole.Id == 0 {
		response.FailJson(ctx, "角色信息已失效", nil)
		return
	}

	if !repo.DeleteById(reqData.Id) {
		response.FailJson(ctx, "删除失败, 请稍后再试", nil)
		return
	}

	response.SuccessJson(ctx, "删除成功", nil)
}

// Disable 角色禁用
func (c *RoleController) Disable(ctx *gin.Context) {
	reqData := &models.AdminRole{}
	rules := validator.NewRules(
		validator.NewRule("id", "角色ID", true, validator.TypeNumberNoneZero),
	)
	if !validator.ShouldBindFromPostForm(ctx, reqData, rules...) {
		return
	}

	hasRole := &models.AdminRole{}
	repo := repository.New(&models.AdminRole{})
	if !repo.Find(hasRole, "is_deleted = 0 AND status = 1 AND id = ?", reqData.Id) || hasRole.Id == 0 {
		response.FailJson(ctx, "角色信息已失效", nil)
		return
	}

	if !repo.DisableById(reqData.Id) {
		response.FailJson(ctx, "操作失败, 请稍后再试", nil)
		return
	}

	response.SuccessJson(ctx, "操作成功", nil)
}

// Enable 角色启用
func (c *RoleController) Enable(ctx *gin.Context) {
	reqData := &models.AdminRole{}
	rules := validator.NewRules(
		validator.NewRule("id", "角色ID", true, validator.TypeNumberNoneZero),
	)
	if !validator.ShouldBindFromPostForm(ctx, reqData, rules...) {
		return
	}

	hasRole := &models.AdminRole{}
	repo := repository.New(&models.AdminRole{})
	if !repo.Find(hasRole, "is_deleted = 0 AND status = 0 AND id = ?", reqData.Id) || hasRole.Id == 0 {
		response.FailJson(ctx, "角色信息已失效", nil)
		return
	}

	if !repo.EnableById(reqData.Id) {
		response.FailJson(ctx, "操作失败, 请稍后再试", nil)
		return
	}

	response.SuccessJson(ctx, "操作成功", nil)
}

// Options 角色选项列表
func (c *RoleController) Options(ctx *gin.Context) {
	roleList := make([]models.AdminRole, 0)
	repo := repository.New(&models.AdminRole{})
	if !repo.SelectAll("sort ASC, created_at DESC", &roleList, "status = 1 AND is_deleted = 0") {
		response.FailJson(ctx, "查询失败, 请稍后再试", nil)
		return
	}

	type roleOption struct {
		Value int64  `json:"value"`
		Label string `json:"label"`
		Icon  string `json:"icon"`
	}

	result := make([]roleOption, 0)
	for _, v := range roleList {
		result = append(result, roleOption{
			Value: v.Id,
			Label: v.Name,
			Icon:  v.Icon,
		})
	}

	response.SuccessJson(ctx, "查询成功", result)
}
